<?php


namespace App\Service\Admin;


use App\Constants\ErrorCode;
use App\Constants\Model\AdminMenu;
use App\Dao\AdminMenuDao;
use App\Dao\AdminRoleDao;
use App\Dao\AdminRoleMenuDao;
use App\Exception\BusinessException;
use App\Model\AdminRole;
use App\Utils\Casbin;
use Hyperf\Database\Model\Collection;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

class AdminRoleService
{
    /**
     * @Inject()
     * @var AdminRoleDao
     */
    protected $adminRoleDao;

    public function __construct()
    {
        $this->casbinInstance = make(Casbin::class, [config('casbin.admin')]);
    }

    /**
     * @param array $where
     * @return \Hyperf\Contract\LengthAwarePaginatorInterface
     */
    public function index(array $where): \Hyperf\Contract\LengthAwarePaginatorInterface
    {
        //不显示默认角色人
        $where['not_show_default'] = 1;
        return $this->adminRoleDao->paginate($where);
    }

    public function all($where)
    {
        //不显示默认角色人
        $where['not_show_default'] = 1;
        return $this->adminRoleDao->select($where, ['id', 'name']);
    }

    /**
     * @param $id
     * @param array $data
     * @return AdminRole
     */
    public function save($id, array $data): AdminRole
    {
        if ($id) {
            //不能修改默认角色人
            $where = [];
            $where['id'] = $id;
            $where['not_show_default'] = 1;
            $role = $this->adminRoleDao->firstOrThrow($where);
        } else {
            $role = new AdminRole();
        }

        $role->fill($data);

        Db::transaction(
            function () use ($role, $data) {
                $role->save();

                //更新角色菜单权限
                $role->adminMenus()->sync($data['menus']);

                //更新角色api访问权限
                $apiMenus = $role->adminMenus()->where('type', AdminMenu::TYPE_API)->get();
                $apiMenuApis = $apiMenus->pluck('api')->toArray();
                $this->casbinInstance->setPermissionsForRole($role->id, $apiMenuApis);
            }
        );

        return $role;
    }

    /**
     * @param int $id
     * @return bool
     */
    public function delete(int $id): bool
    {
        $userIds = $this->casbinInstance->getUsersByRole($id);

        if (!empty($userIds)) {
            throw new BusinessException(ErrorCode::ADMIN_DEFAULT_ROLE_CANT_CHANGE);
        }

        Db::transaction(
            function () use ($id) {
                $where = [];
                $where['id'] = $id;
                $where['not_show_default'] = 1;
                $role = $this->adminRoleDao->firstOrThrow($where);

                if (null == $role) {
                    throw new BusinessException(ErrorCode::ADMIN_ROLE_NOT_FOUND);
                }

                $role->delete();

                //删除角色菜单关联表数据
                di(AdminRoleMenuDao::class)->deleteByRoleId($id);

                //删除角色访问权限
                $this->casbinInstance->deleteRole($id);
            }
        );
        return true;
    }

    /**
     * @param int $id
     * @return mixed
     */
    public function adminMenus(int $id)
    {
        /** @var AdminRole $role */
        $role = $this->adminRoleDao->first(['id' => $id]);

        return $role->adminMenus->pluck('id')->toArray();
    }


}